<?php


namespace plugin\coleopenapi\app\middleware;


use Webman\Event\Event;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;
use Wengg\WebmanApiSign\ApiSignService;

/**
 * api请求日志
 * Class StatApiMiddleware
 * @package plugin\coleopenapi\app\middleware
 */
class RequestLogMiddleware implements MiddlewareInterface
{
    public function process(Request $request, callable $handler): Response
    {
        $startTime = microtime(true);
        $ip = $request->getRealIp($safe_mode = true);

        $service = new ApiSignService;
        $config = $service->getConfig();
        $fields = $config['fields'];

        $method = request()->header("method", request()->input("method"));
        $appKey = request()->header($fields['app_key'], request()->input($fields['app_key']));

        /**
         * @var Response
         */
        $response = $handler($request);

        $finishTime = microtime(true);
        $costTime = ($finishTime - $startTime) * 1000;
        switch (true) {
            case !empty($response->getHeader('Content-Type')) && 'application/json' === strtolower($response->getHeader('Content-Type')):
                $body = json_decode($response->rawBody(), true);
                break;
            default:
                $body = 'Non Json data';
                break;
        }
        //因为openapi插件是统一对外的 所以controller和action在DispatchController重新解析赋值的
        $transfer = $request->controller . '::' . $request->action;
        if ('::' === $transfer) {
            $transfer = $request->path();
        }

        $code = $response->getStatusCode();
        $code = is_int($code) ? $code : 500;
        $time = date('Y-m-d H:i:s.', (int)$startTime) . substr($startTime, 11);
        $details = [
            'time' => $time,   // 请求时间（包含毫秒时间）
            'run_time' => $costTime, // 运行时长
            'code' => $code,
            'ip' => $request->getRealIp($safe_mode = true) ?? '',// 请求客户端IP
            'url' => $request->fullUrl() ?? '',// 请求URL
            'method' => $request->method() ?? '',// 请求方法
            'request_param' => $request->all() ?? [],// 请求参数
            'request_header' => $request->header() ?? [],// 请求头
            'cookie' => $request->cookie() ?? [],// 请求cookie
            'session' => $request->session()->all() ?? [],// 请求session
            'response_code' => $response->getStatusCode() ?? '',// 响应码
            'response_header' => $response->getHeaders() ?? [],// 响应头
            'response_body' => $body,     // 响应数据
        ];
        $success = $code < 400;
        $data = [
            'time' => date('Y-m-d H:i:s.', (int)$startTime) . substr($startTime, 11),
            'ip' => $ip,
            'date' => date("Y-m-d"),
            'request_id' => $request->request_id ?? "",
            'transfer' => $transfer,
            'cost_time' => $costTime,
            'success' => $success ? 1 : 0,
            'code' => $code,
            'app_key' => $appKey,
            'method' => $method,
            'details' => json_encode($details, 320),
        ];
        Event::emit('openapi.request.log', $data);
        return $response;
    }
}